#ifndef __ULCORE_HISTORY_H__
#define __ULCORE_HISTORY_H__

#include "ULCore_Serial.h"
#include <vector>

//For quick lookup
struct ULC_HistoryIndexMap{
	int sn;
	char date[DATE_ALIGN_SIZE];	
	int index;
};

class ULC_History{
protected:
	int totalSerials;
	int latestSerial;
	ULC_Serial *serials; //Store every serial
	struct ULC_HistoryIndexMap *indexMap;
	list<ULC_Serial *> hashSerials[16 + 1]; //Indexed by blue number
	list<ULC_Serial *> repeatedRoots; //Repeated root nodes
	bool repeatedFound;
	bool initFlag; //Whether member "serials" has been setup
	bool hashFlag; //Whether member "hashSerials" has been setup
	bool mapFlag; //Whether member "indexMap" has been setup
private:
	int OptimizedBinarySearchSN(int leftIndex, int rightIndex, int serialNo);
	int LookupIndex(int serialNo);
	int LookupIndex(const char *date);
	void SetupHashSerials();
	void ClearHashSerials();
	void SetupIndexMap();
	void HashSetupRepeatedSerials(int hashList);
	void SetupRepeatedSerials();
	ULC_Serial *BinarySearchSerialSN(int serialNo);
public:
	ULC_History();
	~ULC_History();
public:
	//History data file operation methods
	int ParseBinHistory(const char *binFileName); //Read binary history data file(If already parsed, this method will re-parse)
	int UpdateBinHistory(const char *txtFileName, const char *binFileName); //Update binary history data file from txt history file 
	int GenerateBinHistory(const char *txtFileName, const char *binFileName);//Generate binary history data file from txt history data file
public:
	//Lookup methods
	ULC_Serial *LookupSerial(int serialNo); //Lookup by serial number
	ULC_Serial *LookupSerial(const char *date); //Lookup by date
	ULC_Serial *LookupRange(int startSerialNo, int &count); //Caller must check count to see if it has been modified
	ULC_Serial *LookupRange(const char *startDate, int &count);
	int LookupSerial(list<ULC_Serial *> &resultList, ULC_Balls &balls);//Must have blue ball in argument balls
	int LookupSerialsByBlueBall(list<ULC_Serial *> &resultList, int blueNumber);
public:
	//Properties retrieving methods
	bool RepeatedSerialsFound();
	void ShowRepeatedSerials();	
	ULC_Serial *GetLatestSerial();
	ULC_Serial *GetLatestSerials(int &nSerials);
	int GetLatestNSerialsBlues(list<int> &result, int &nSerials);
	int GetLatestNSerialsWithBlueNumber(list<ULC_Serial *> &result, int &nSerials, int blueNumber);
	int GetTotalSerials();
	int CaculateGap(ULC_Serial *serial1, ULC_Serial *serial2);//How many serials between serial1 and serial2, return positive number(the order of serial1 and serial2 is not important)
	int CaculateGap(int serialNo1, int serialNo2);
	//Friend class is ULC_Statistic
	friend class ULC_Statistic;
};

#endif /*__ULCORE_HISTORY_H__*/
